#ifndef _SMART_STR_H
#define _SMART_STR_H

#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <pthread.h>

typedef struct {
	volatile uint32_t rpos;
	volatile uint32_t tpos;
	uint32_t size;
	uint32_t rx_size;
	uint8_t rx_skip;
	uint8_t *buf;
	pthread_mutex_t lock;
	pthread_cond_t cond;
} smart_str_t;

#define defSmartStr(var, size) \
  static uint8_t ss_##var##_buf[size]; \
  smart_str_t ss_##var = {0, 0, size, 0, 0, ss_##var##_buf}

#define extSmartStr(var) extern smart_str_t ss_##var
#define refSmartStr(var) (&ss_##var)

#define smart_str_init(var) _smart_str_init(&ss_##var)
#define smart_str_init_ex(var, buf, size) _smart_str_init_ex(&ss_##var, buf, size)
#define smart_str_clear(var) _smart_str_clear(&ss_##var)
#define smart_str_destroy(var) _smart_str_destroy(&ss_##var)

#define smart_str_signal(var) _smart_str_signal(&ss_##var)
#define smart_str_put_size(var) _smart_str_put_size(&ss_##var)
#define smart_str_put(var, buf, len) _smart_str_put(&ss_##var, (const uint8_t *) (buf), len)
#define smart_str_get_size(var) _smart_str_get_size(&ss_##var)
#define smart_str_get(var, buf, len, ms) _smart_str_get(&ss_##var, (uint8_t*) (buf), len, ms)
#define smart_str_readline(var, buf, len) _smart_str_readline(&ss_##var, (char*) (buf), len)
#define smart_str_vprintf(var, buf, len, fmt, ap) _smart_str_vprintf(&ss_##var, buf, len, fmt, ap)
#define smart_str_sprintf(var, buf, len, fmt, args...) _smart_str_sprintf(&ss_##var, buf, len, fmt, ##args)
#define smart_str_aprintf(var, fmt, args...) _smart_str_aprintf(&ss_##var, fmt, ##args)
#define smart_str_aprintf2(var, fmt, args...) _smart_str_aprintf2(&ss_##var, fmt, ##args)
#define smart_str_aprintf4(var, fmt, args...) _smart_str_aprintf4(&ss_##var, fmt, ##args)

void _smart_str_init(smart_str_t *ss);
void _smart_str_init_ex(smart_str_t *ss, uint8_t *buf, uint32_t size);
void _smart_str_clear(smart_str_t *ss);
void _smart_str_destroy(smart_str_t *ss);

void _smart_str_signal(smart_str_t *ss);
uint32_t _smart_str_put_size(smart_str_t *ss);
bool _smart_str_put(smart_str_t *ss, const uint8_t *buf, uint32_t len);
uint32_t _smart_str_get_size(smart_str_t *ss);
uint32_t _smart_str_get(smart_str_t *ss, uint8_t *buf, uint32_t len, uint32_t msec);
bool _smart_str_readline(smart_str_t *ss, char *buf, uint32_t len);
void _smart_str_vprintf(smart_str_t *ss, char *buf, size_t len, const char *fmt, va_list ap);
void _smart_str_sprintf(smart_str_t *ss, char *buf, size_t len, const char *fmt, ...) __attribute__ ((format(printf, 4, 5)));
void _smart_str_aprintf(smart_str_t *ss, const char *fmt, ...) __attribute__ ((format(printf, 2, 3)));
void _smart_str_aprintf2(smart_str_t *ss, const char *fmt, ...) __attribute__ ((format(printf, 2, 3)));
void _smart_str_aprintf4(smart_str_t *ss, const char *fmt, ...) __attribute__ ((format(printf, 2, 3)));

#endif
